import * as THREE from 'three';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js';
import GUI from 'three/examples/jsm/libs/lil-gui.module.min.js';
import TWEEN from 'tween.ts';

export default class DefaultScene {
    static readonly DefaultCanvasWidth:number = 800;
    static readonly DefaultCanvasHeight:number = 600;
    readonly gui = new GUI();
    readonly scene = new THREE.Scene();
    readonly renderer = new THREE.WebGLRenderer({ antialias: true });
    camera: any;
    controls: any;
    composer?: EffectComposer;
    cssRender?: CSS2DRenderer;
    readonly size = new THREE.Vector2();
    readonly animates: Function[] = [];
    isLoop: boolean = true
    constructor() {
        this.renderer.setSize(DefaultScene.DefaultCanvasWidth, DefaultScene.DefaultCanvasHeight);
        this.usePerCamera(); // 默认使用透视相机
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.addEventListener('change',  () => {
            console.log('camera.position', this.camera.position);
        });
    }
    init(domRef: any) {
        setTimeout(() => {
            domRef.value.appendChild(this.renderer.domElement);
        });
        this.renderer.getSize(this.size);
        requestAnimationFrame(this.loop.bind(this));
    }
    usePerCamera():void {
        this.scene.remove(this.camera);
        this.camera = new THREE.PerspectiveCamera(75, DefaultScene.DefaultCanvasWidth / DefaultScene.DefaultCanvasHeight, 0.1, 1000); // 默认使用透视相机
        this.camera.position.set(300, 300, 300);
        this.camera.lookAt(0, 0, 0);
        this.scene.add(this.camera);
        this.controls && (this.controls.object = this.camera);
    }
    useOrthCamera():void {
        this.scene.remove(this.camera);
        this.camera = new THREE.OrthographicCamera(-DefaultScene.DefaultCanvasWidth / 1.5, DefaultScene.DefaultCanvasWidth / 1.5, DefaultScene.DefaultCanvasHeight / 1.5, -DefaultScene.DefaultCanvasHeight / 1.5, 1, 8000);
        this.camera.position.set(300, 300, 300);
        this.camera.lookAt(0, 0, 0);
        this. scene.add(this.camera);
        this.controls && (this.controls.object = this.camera);
    }
    addLoops(...animates: any[]){
        this.animates.push.apply(this.animates, animates);
    }
    resize(width: number, height: number) {
        this.renderer.setSize(width, height);
        this.renderer.getSize(this.size);
        if (this.camera.aspect) {
            this.camera.aspect = width / height;
        }
        this.camera.updateProjectionMatrix();
    }
    loop(time: number) {
        if (!this.isLoop) {
            return
        }
        TWEEN.update(time);
        for (const animate of this.animates) {
            animate(time);
        }
        if (this.composer) {
            this.composer.render();
        } else {
            this.renderer.render(this.scene, this.camera);
        }
        if (this.cssRender) {
            this.cssRender.render(this.scene, this.camera);
        }
        requestAnimationFrame(this.loop.bind(this));
    }
    stopLoop() {
        this.isLoop = false
    }
}
